﻿using FTBS.Models.Entities;
using FTBS.Models.Entities.Concert;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;

namespace FTBS.Models.BLO
{
    public class HomeBLO
    {
        private TheaterBLO _theaterBlo = new TheaterBLO();

        private double deg2rad(double deg)
        {
            return (deg * Math.PI / 180.0);
        }

        private double rad2deg(double rad)
        {
            return (rad / Math.PI * 180.0);
        }

        private double Distance(double lat1, double lon1, double lat2, double lon2, char unit)
        {
            double theta = lon1 - lon2;
            double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
            dist = Math.Acos(dist);
            dist = rad2deg(dist);
            dist = dist * 60 * 1.1515;
            if (unit == 'K')
            {
                dist = dist * 1.609344;
            }
            else if (unit == 'N')
            {
                dist = dist * 0.8684;
            }
            return (dist);
        }

        public TheaterPositionEntity CalculateDistance(string originLat, string originLong, string destLat, string destLong)
        {
            // Calculate distance from origin to destination
            string url = "http://maps.googleapis.com/maps/api/distancematrix/xml?";
            url += "origins=" + originLat + "," + originLong;
            url += "&destinations=" + destLat + "," + destLong;
            url += "&mode=driving";
            url += "&sensor=false";
            return DownloadXML3(url);
        }

        public TheaterPositionEntity DownloadXML3(string url)
        {
            TheaterPositionEntity theaterPosition = new TheaterPositionEntity();

            Stream stream = DownloadResource(url);
            DataSet ds = new DataSet();
            ds.ReadXml(stream);
            theaterPosition.Time = ds.Tables["duration"].Rows[0][1].ToString().Trim();
            theaterPosition.Distance = Convert.ToDouble(ds.Tables["distance"].Rows[0][0]);
            theaterPosition.DistanceString = ds.Tables["distance"].Rows[0][1].ToString().Trim();
            ds.Dispose();
            stream.Close();
            stream.Dispose();
            return theaterPosition;
        }

        public static Stream DownloadResource(string url)
        {
            MemoryStream stream = null;

            try
            {
                WebClient client = new WebClient();
                client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
                byte[] data = client.DownloadData(url);
                stream = new MemoryStream(data);
                client.Dispose();
            }
            catch (WebException ex)
            {
                throw ex;
            }

            return stream;
        }

        /// <summary>
        /// Convert Theater object to TheaterConcertEntity object
        /// </summary>
        /// <param name="theater"></param>
        /// <returns></returns>
        private TheaterConcertEntity ConvertObjectTheater(Theater theater)
        {
            TheaterConcertEntity result = new TheaterConcertEntity();
            result.TheaterId = theater.TheaterId;
            result.TheaterName = theater.TheaterName;
            result.Address = theater.Address;
            result.PhoneNumber = theater.PhoneNumber;
            result.UserName = theater.UserName;
            result.IsDeleted = theater.IsDeleted;
            result.Latitude = theater.Latitude;
            result.Longitude = theater.Longitude;
            result.ImageURL = theater.ImageURL;
            return result;
        }

        public List<TheaterConcertEntity> GetListNearestTheater(string customerLat, string customerLong)
        {
            List<TheaterConcertEntity> lstTheaterResult = new List<TheaterConcertEntity>();
            List<Theater> lstAllTheater = new List<Theater>();
            lstAllTheater = _theaterBlo.GetAllTheaterInfo();
            List<TheaterPositionEntity> listPosition = new List<TheaterPositionEntity>();
            foreach (var item in lstAllTheater)
            {
                TheaterPositionEntity theaterPostion = new TheaterPositionEntity();
                theaterPostion = CalculateDistance(customerLat, customerLong, item.Latitude, item.Longitude);
                theaterPostion.TheaterId = item.TheaterId;
                listPosition.Add(theaterPostion);
            }

            listPosition = listPosition.OrderBy(rs => rs.Distance).ToList();
            if (listPosition.Count() > 3)
            {
                for (int i = 0; i < 3; i++)
                {
                    var theaterResult = (from t in lstAllTheater
                                         where t.TheaterId == listPosition[i].TheaterId
                                         select t).FirstOrDefault();
                    TheaterConcertEntity theaterConcertEnt = new TheaterConcertEntity();
                    theaterConcertEnt = ConvertObjectTheater(theaterResult);
                    theaterConcertEnt.Time = listPosition[i].Time;
                    theaterConcertEnt.Distance = listPosition[i].Distance;
                    theaterConcertEnt.DistanceString = listPosition[i].DistanceString;
                    lstTheaterResult.Add(theaterConcertEnt);
                }
            }
            else
            {
                foreach (var item in listPosition)
                {
                     var theaterResult = (from t in lstAllTheater
                                         where t.TheaterId == item.TheaterId
                                         select t).FirstOrDefault();
                     TheaterConcertEntity theaterConcertEnt = new TheaterConcertEntity();
                     theaterConcertEnt = ConvertObjectTheater(theaterResult);
                     theaterConcertEnt.Time = item.Time;
                     theaterConcertEnt.Distance = item.Distance;
                     theaterConcertEnt.DistanceString = item.DistanceString;
                     lstTheaterResult.Add(theaterConcertEnt);
                }
            }
            return lstTheaterResult;
        }

    }
}